package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Category;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private SkuService skuService;

    @Autowired
    private AmqpTemplate amqpTemplate;


    @Override
    public PageDTO<SpuDTO> pageSpu(Long curPage, Long rows, Long bid, Long cid, Long sid, Boolean saleable) {
        //分页查询
        IPage<Spu> page = new Page<Spu>(curPage,rows);
        //查询条件
        QueryWrapper<Spu> queryWrapper = new QueryWrapper<Spu>()
                .eq(bid != null, "brand_id", bid)
                .eq(cid != null, "cid3", cid)
                .eq(sid != null, "id", sid)
                .eq(saleable != null, "saleable", saleable);
        this.page(page,queryWrapper);


        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(page.getRecords());
        for (SpuDTO spuDTO : spuDTOS) {

            spuDTO.setBrandName(this.getBrandNameByBid(spuDTO.getBrandId()));

            spuDTO.setCategoryName(this.getCategoryNameByCid(spuDTO.getCategoryIds()));
        }

        //结果封装
        PageDTO<SpuDTO> pageDTO = new PageDTO<>();
        pageDTO.setTotal(page.getTotal());
        pageDTO.setTotalPage(page.getPages());
        pageDTO.setItems(spuDTOS);

        return pageDTO;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public void saveSpu(SpuDTO spuDTO) {
        //保存商品信息
        Spu spu = spuDTO.toEntity(Spu.class);
        this.save(spu);
        //保存商品详情信息
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();

        if(spuDetailDTO != null) {
            spuDetailDTO.setSpuId(spu.getId());
            spuDetailService.save(spuDetailDTO.toEntity(SpuDetail.class));
        }
        //保存商品sku信息
        List<SkuDTO> skus = spuDTO.getSkus();
        if(!CollectionUtils.isEmpty(skus))
        {
            //将skuDTO转换成sku
            List<Sku> skuList = skus.stream()
                    .map(skuDTO -> {
                        Sku sku = skuDTO.toEntity(Sku.class);
                        sku.setSpuId(spu.getId());
                        sku.setSaleable(true);
                        return sku;
                    }).collect(Collectors.toList());
            //批量保存
            skuService.saveBatch(skuList);
        }

        String routingKey = "item.up";
        amqpTemplate.convertAndSend("jhj",routingKey,spuDTO.getId());
    }

    /**
     * 注意spu和sku关联
     * @param sid 商品id
     * @param saleable 上下架
     */
    @Transactional
    @Override
    public void updateSpuSaleable(Long sid, Boolean saleable) {

        if(sid != null && saleable != null){
            Spu spu = new Spu();
            spu.setId(sid);
            spu.setSaleable(saleable);
            //修改spu
            this.updateById(spu);
            //修改sku

            List<Sku> skuList = skuService.list(new QueryWrapper<Sku>().eq("spu_id", sid));
            if(!CollectionUtils.isEmpty(skuList)){
                skuList.forEach(sku -> sku.setSaleable(saleable));
            }

            skuService.updateBatchById(skuList);
            //发送消息到mq
            String routingKey = saleable ? "item.up":"item.down";
            amqpTemplate.convertAndSend("jhj",routingKey,sid);

        }
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        Spu spu = this.getById(id);
        SpuDTO spuDTO = new SpuDTO(spu);
        //根据商品id查询商品详情
        SpuDetail spuDetail = spuDetailService.getOne(new QueryWrapper<SpuDetail>().eq("spu_id", id));
        //根据商品id查询商品sku
        List<Sku> skuList = skuService.list(new QueryWrapper<Sku>().eq("spu_id", id));
        //封装数据
        spuDTO.setSkus(SkuDTO.convertEntityList(skuList));
        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));

        spuDTO.setBrandName(getBrandNameByBid(spuDTO.getBrandId()));
        spuDTO.setCategoryName(getCategoryNameByCid(spuDTO.getCategoryIds()));
        return spuDTO;
    }

    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    @Override
    public void updateSpu(SpuDTO spuDTO) {

        //1.获取请求中携带的商品、商品细节、skus信息
        Spu spu = spuDTO.toEntity(Spu.class);
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        //判断不同信息是否有值，有则修改
        //2 判断并修改spu
        if(spu == null ||spu.getId() != null){
            this.updateById(spu);
        }
        //3 判断并修改spuDetail
        if(spuDetailDTO != null){
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            spuDetailService.updateById(spuDetail);
        }

        //4 判断并修改skus
        ArrayList<Sku> toAdd = new ArrayList<>();
        ArrayList<Sku> toDelete = new ArrayList<>();
        ArrayList<Sku> toUpdate = new ArrayList<>();
        if(skuDTOList!=null){
            List<Sku> skuList = skuDTOList.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
            for (Sku sku : skuList) {
                if(sku.getId() == null){
                    toAdd.add(sku);
                }else if(sku.getSaleable() == null){
                    toUpdate.add(sku);
                }else{
                    toDelete.add(sku);
                }
            }

            if(!CollectionUtils.isEmpty(toAdd)){
                skuService.saveBatch(toAdd);
            }
            if(!CollectionUtils.isEmpty(toDelete)){
                skuService.removeByIds(toDelete.stream().map(Sku::getId).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(toUpdate)){
                skuService.updateBatchById(toUpdate);
            }
        }


       /* if(skuDTOList!=null){
            //将skuDTO集合转换成sku集合
            List<Sku> skus = skuDTOList.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
            for (Sku sku : skus) {
                //4.1 判断sku对象是否有id,无id则添加
                if(sku.getId() == null){
                    skuService.save(sku);
                    continue;
                }

                //4.2 sku有id,判断是否携带saleable,没有则更新
                if(sku.getSaleable() == null){
                    skuService.updateById(sku);
                }else{
                    //4.3 到达此处的sku有id,并且携带了saleable属性
                    skuService.removeById(sku.getId());
                }

            }
        }*/
    }

    @Override
    public SpuDTO querySpuById(Long sid) {

        return new SpuDTO(this.getById(sid));
    }

    /**
     * 根据分类id查询分类名
     * @param categoryIds 分类id
     * @return
     */
    public String getCategoryNameByCid(List<Long> categoryIds) {
        //判断分类id集合是否为空
        if(!CollectionUtils.isEmpty(categoryIds)){
            //根据分类id集合获取对应分类名称集合
            List<Category> categoryList = categoryService.listByIds(categoryIds);
            String cname = categoryList.stream()
                    .map(Category::getName)
                    .collect(Collectors.joining("/"));
            return cname;
        }
        return null;
    }

    /**
     * 根据品牌id查询品牌名
     * @param bid 品牌id
     * @return
     */
    private String getBrandNameByBid(Long bid) {
        if(bid != null){
            return brandService.getById(bid).getName();
        }
        return null;
    }
}
